#pragma once
#include <iostream>
#include <assert.h>
//#include <initializer_list>
using std::cout;
using std::cin;
using std::endl;

namespace real
{
    template <class T>
    struct Node
    {
        Node* _prev = nullptr;
        Node* _next = nullptr;
        T _data;

    //public:
        Node(const T& val=T())
            :_prev(nullptr)
            ,_next(nullptr)
            ,_data(val)
        {}
    };

    // Ref,Ptr 代指 (const T& / T& ) 和 ( const T* / T* )
    template <class T, class Ref, class Ptr>
    struct list_iterator
    {
        Node<T>* _node;
        //typedef list_iterator<T> Self;
        typedef list_iterator<T, Ref, Ptr> Self;

        // 要的就是浅拷贝, 修改迭代器指向的内容同步影响到Node内容
        list_iterator(Node<T>* node)
            :_node(node) 
        {}
        
		// 一旦实现了拷贝构造函数, 就会覆盖默认的拷贝构造函数, 会导致后置++中*this被判定为拷贝构造
		// 在这里不是特别必要实现拷贝构造函数
        //list_iterator(const Self& it)
        //    :_node(it._node)
        //{}

        Ref operator*()  // const T& / T&
        {
            return _node->_data;
        }

        Ptr operator->() // const T* / T*
        {
            return &(_node->_data);
        }

        Self& operator++()
        {
            _node = _node->_next;
            return *this;
        }

        // 后置++ 传值返回而不是引用
        Self operator++(int)
        {
            // Self& oldself = *this; // 不能是引用, 否则出作用域销毁
            Self oldself(*this);
            //Self oldself(_node);
            _node = _node->_next;
            return oldself;
        }

        Self& operator--()
        {
            _node = _node->_prev;
            return *this;
        }

        Self operator--(int)
        {
            Self oldself = *this;
            _node = _node->_prev;
            return oldself;
        }

        bool operator==(const Self& other) const
        {
            return _node == other._node;
        }

        bool operator!=(const Self& other) const
        {
            return _node != other._node;
        }
    };

    template <class T>
    class list
    {
    
    public:
        typedef list_iterator<T, T&, T*> iterator;
        typedef list_iterator<T, const T&, const T*> const_iterator;
        
        void initilize()
        {
            _head = new Node<T>;
            _head->_next = _head->_prev = _head;
            _size = 0;
        }

        list()
        {
            initilize();
        }

        list(const list& other)
        {
            initilize();
            const_iterator it = other.begin();
            while (it != other.end())
            {
                push_back(*(it++));
            }
        }

        list( const std::initializer_list<T>& init_list )
        {
            initilize();
            for(auto &e:init_list)
            {
                push_back(e);
            }
        }

        //list& operator=(const list& other)
        //{
        //    clear();
        //    for (auto& e : other)
        //    {
        //        push_back(e);
        //    }
        //    return *this;
        //}

        // 现代写法
        list<T>& operator=(list<T> other)
        {
            swap(other);
            return *this;
        }

        void swap(list<T> other)
        {
            std::swap(_head, other._head);
            std::swap(_size, other._size);
        }

        Node<T>* get_node(const T& val)
        {
            Node<T>* newnode = new Node<T>(val);
            return newnode;
        }

        void push_back(const T& val)
        {
            /*Node<T>* newnode = get_node(val);
            newnode->_next = _head;
            newnode->_prev = _head->_prev;

            _head->_prev->_next = newnode;
            _head->_prev = newnode;

            ++_size;*/
            insert(end(), val);
        }

        void push_front(const T& val)
        {
            insert(begin(), val);
        }

        // insert不会产生迭代器视效问题, 但是可以把newnode本身返回
        iterator insert(iterator pos, const T& val)
        {
            Node<T>* newnode = get_node(val);
            Node<T>* prev_node = (pos._node)->_prev;
            newnode->_next = (pos._node);
            newnode->_prev = prev_node;
            prev_node->_next = newnode;
            (pos._node)->_prev = newnode;

            ++_size;
            return newnode;
        }

        // erase会产生迭代器视效的问题, 所以传下一个节点作为返回值
        iterator erase(iterator pos)
        {
            assert(pos != end()); // end()隐式转换: 哨兵位节点不允许删除
            Node<T>* cur = pos._node;
            Node<T>* prev_node = cur->_prev;
            Node<T>* next_node = cur->_next;
            delete cur;
            prev_node->_next = next_node;
            next_node->_prev = prev_node;
            --_size;
            return next_node;
        }

        size_t size()
        {
            return _size;
        }

        iterator begin()
        {
            /*iterator it  = iterator(_head->_next);
            return it;*/

            //return iterator(_head->_next); // 匿名对象
            return _head->_next;  // 走隐式类型转换
        }

        iterator end()
        {
            /*iterator it = iterator(_head);
            return it;*/

            return _head;
        }

        const_iterator begin() const
        {
            return _head->_next;  // 走隐式类型转换
        }

        const_iterator end() const
        {
            return _head;
        }

        void clear()
        {
            cout << "clear()" << endl;
            iterator it = begin();
            while (it != end())
            {
                it = erase(it);
            }
        }

        ~list()
        {
            cout << "~list()" << endl;
            clear();
            delete _head;
            _head = nullptr;
        }

    private:
        Node<T>* _head;
        size_t _size;
    };

    template <class Container>
    void print_container(const Container& v) // 需要实现 const 迭代器
    {
        // const iterator // const修饰iterator本身, 不能自增或自减
        // const_iterator // 额外定义一个迭代器类: 指向的内容不能修改
        
        for (auto &e : v)
        {
            cout << e << " ";
        }
        cout << endl;

        /*typename Container::const_iterator it = v.begin();
        while (it != v.end())
        {
            cout << (*(it++)) << " ";
        }
        cout << endl;*/
    }

    void test_list1()
    {
        list<int> li;
        li.push_back(1);
        li.push_back(2);
        li.push_back(3);
        li.push_back(4);
        li.push_front(0);
        typename list<int>::iterator pos = li.begin();
        
        ++pos;
        ++pos;
        li.insert(pos,100);

        for (auto &e : li)
        {
            cout << (e) << " ";
        }
        cout << endl;

        li.erase(li.begin());
        for (auto& e : li)
        {
            cout << (e) << " ";
        }
        cout << endl;

        pos++;
        li.erase(pos);
        for (auto& e : li)
        {
            cout << (e) << " ";
        }
        cout << endl;
    }

    class TEST
    {
    public:
        int _val = 0;

        TEST(int v=0)
            :_val(v)
        {
        }
    };

    void test_list2()
    {
        list<TEST> lt;
        lt.push_back(1);
        lt.push_back(2);
        lt.push_back(3);

        for (list<TEST>::iterator it = lt.begin(); it != lt.end(); ++it)
        {
            cout << (*it)._val << " ";

            // 特殊处理, 本来应该是两个 `->` 才合理, 为了可读性, 省略了一个 `->`
            //cout << (it.operator->()->_val) << " ";
            cout << (it->_val) << " ";
        }
        cout << endl;
    }

    void test_list3()
    {
        list<int> li;
        li.push_back(1);
        li.push_back(2);
        li.push_back(3);

        print_container(li);
    }

    // 测试拷贝构造
    void test_list4()
    {
        list<int> li;
        li.push_back(1);
        li.push_back(2);
        li.push_back(3);
        li.push_back(4);
        li.push_back(5);

        list<int> lic(li);
        print_container(lic);
    }

    // 测试赋值重载
    void test_list5()
    {
        list<int> li;
        li.push_back(1);
        li.push_back(2);
        li.push_back(3);
        li.push_back(4);
        li.push_back(5);

        list<int> lic;
        lic.push_back(10);
        lic.push_back(20);
        lic.push_back(30);
        print_container(lic);

        lic = li;
        print_container(lic);
        print_container(li);
    }

    // 测试初始话列表构造
    void func(const list<int>& li)
    {
        print_container(li);
    }

    void test_list6()
    {
        list<int> li1({ 1,2,3,4,5,6,7,8 }); // 直接构造 真正的使用方式
        print_container(li1);
        func(li1);
        func({9,8,7,6,5,4,3,2,1});

        // 走隐式类型转换
        list<int> li2 = {1,2,3,4,5,6};
        print_container(li2);

        list<std::string> ls1 = { "1", "2", "334", "手动"};
        print_container(ls1);

        list<double> ld1 = { 1,2,3,4.1,5.5 };
        print_container(ld1);


    }
}